﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Awesome.Extensions.Disposable;
using En = System.Linq.Enumerable;

namespace Awesome.Extensions.Enumerable
{
    public static class IE
    {
        /// <summary>
        /// Creates a new IEnumerable
        /// </summary>
        public static IEnumerable<T> New<T>(params T[] values)
        {
            return values.ToArray();
        }

        // Todo: check if LazyGenerator might be implemented 
        // Todo: using yield return
        private class LazyGenerator<T> : IEnumerable<T>
        {
            private readonly Func<IEnumerable<T>> _generator;

            public LazyGenerator(Func<IEnumerable<T>> generator)
            {
                _generator = generator;
            }


            private class Enumenator : IEnumerator<T>
            {
                private readonly Func<IEnumerable<T>> _generator;
                private IEnumerator<T> _enumerator;

                private void CheckEnumenator()
                {
                    if (_enumerator == null)
                        _enumerator = _generator().GetEnumerator();
                }

                public Enumenator(Func<IEnumerable<T>> generator)
                {
                    _generator = generator;
                }

                [DebuggerStepThrough]
                public bool MoveNext()
                {
                    CheckEnumenator();
                    return _enumerator.MoveNext();
                }

                [DebuggerStepThrough]
                public void Reset()
                {
                    CheckEnumenator();
                    _enumerator.Reset();
                }

                public T Current
                {
                    [DebuggerStepThrough]
                    get
                    {
                        CheckEnumenator();
                        return _enumerator.Current;
                    }
                }


                object IEnumerator.Current
                {
                    [DebuggerStepThrough]
                    get
                    {
                        CheckEnumenator();
                        return _enumerator.Current;
                    }
                }

                [DebuggerStepThrough]
                public void Dispose()
                {
                    _enumerator.SafeDispose();
                }
            }

            public IEnumerator<T> GetEnumerator()
            {
                throw new NotImplementedException();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

        /// <summary>
        /// Invokes generator on start of enumeration to perform true lazynes
        /// </summary>
        public static IEnumerable<T> Lazy<T>(Func<IEnumerable<T>> generator)
        {
            return new LazyGenerator<T>(generator);
        }

        public static IEnumerable<int> Range(int start, int count)
        {
            return En.Range(start, count);
        }
    }
}
